#include "mfMesh.h"
#include <stdio.h>
#include <list>
#include "kernel/feInterpolation.h"
#include <math.h>
#include <algorithm>

mfMesh::mfMesh(mfMesh *iMesh, double iPointCoef)
{
	ActElementsCount = ActPointsCount = 0;

	for(int i=0; i<iMesh->ActElementsCount; i++)
	{
		Elements[i] = iMesh->Elements[i];
		Elements[i].SetMesh(this);
	}
	

	//copy points
	for(unsigned int i=0; i<iMesh->ActPointsCount; i++)
		Points[i].X = iMesh->Points[i].X*iPointCoef;
}


//----------------------------------------------------------------------------------------------------------------------------------
void mfMesh::ScalePoints(double iCoef)
{
	for(unsigned int i=0; i<ActPointsCount; i++)
		Points[i].X *= iCoef;
}


//----------------------------------------------------------------------------------------------------------------------------------
void mfMesh::CopyFrom(mfMesh *iMesh)
{
	ClearMesh();

	for(int i=0; i<iMesh->ActElementsCount; ++i)
	{
		Elements[i] = iMesh->Elements[i];
		Elements[i].SetMesh(this);
	}


	//copy points	
	CopyMemory(&Points[0], &iMesh->Points[0], iMesh->ActPointsCount*sizeof(Points[0]));
}


//----------------------------------------------------------------------------------------------------------------------------------
void mfMesh::PushElement(feElement *iElement)
{
	feQuadraticElement1d *e = dynamic_cast<feQuadraticElement1d*>(iElement);
	if(e)
	{
// 		std::list<feLinearElement1d>::iterator i = Elements.begin();
// 		for(; i!=Elements.end(); ++i)
// 		{
// 			if(i->NodeIndex(0) > e->NodeIndex(0))
// 			{
// 				Elements.insert(i, 1, *e);
// 				return;
// 			}
// 		}

		Elements[ActElementsCount] = *e;
		ActElementsCount++;
	}
}


//----------------------------------------------------------------------------------------------------------------------------------
void mfMesh::PushNode(fePoint *iPoint)
{
	if(iPoint)
	{
		Points[ActPointsCount] = *iPoint;
		ActPointsCount++;
	}
}


//---------------------------------------------------------------------------------------------------------------------------------
bool mfMesh::SaveToFile(char *iFname)
{
	//try to open
	FILE *fp = fopen(iFname, "wb");
	if(!fp) return false;

	
	//save stride
	unsigned int size = sizeof(double);
	fwrite(&size, sizeof(size), 1, fp);


	//save points count and layers count
	size = (unsigned int)ActPointsCount;
	fwrite(&size, sizeof(size), 1, fp);

	//save x
	fwrite(&Points[0], sizeof(Points[0]), ActPointsCount, fp);

	
	//done
	fclose(fp);
	return true;
}


//---------------------------------------------------------------------------------------------------------------------------------
bool mfMesh::LoadFromFile(char *iFname)
{
	//try to open
	FILE *fp = fopen(iFname, "rb");
	if(!fp) return false;


	//read stride
	unsigned int stride = 0;
	fread(&stride, sizeof(unsigned int), 1, fp);
	if(stride != sizeof(feReal))
	{
		fclose(fp);
		return false;
	}
	
	
	//read points count
	unsigned int pcount = 0;
	fread(&pcount, sizeof(unsigned int), 1, fp);


	//resize vectors
	ActPointsCount = pcount;


	//read points
	fread(&Points[0], sizeof(fePoint), pcount, fp);


	//done
	fclose(fp);
	return true;
}


//---------------------------------------------------------------------------------------------------------------------------------
void mfMesh::SplitElement(int iIndex, double iTau)
{
// 	//get nodes
// 	int nodes[3];
// 	std::list<feLinearElement1d>::iterator i = Elements.begin();
// 	std::advance(i, iIndex);
// 	i->GetIndeces(nodes);
// 
// 
// 	//add new nodes
// 	double h = Points[nodes[1]].X - Points[nodes[0]].X;
// 
// 	fePoint p01;
// 	p01.X = Points[nodes[0]].X + h/(1+iTau);
// 
// 
// 	//insert points
// 	Points.insert(Points.begin()+nodes[0]+1, 1, p01);
// 
// 	std::list<feLinearElement1d>::iterator el = i;
// 	++i;
// 	Elements.insert(i, 1, feLinearElement1d(*el, nodes[0]+1));
}


//---------------------------------------------------------------------------------------------------------------------------------
void mfMesh::RebindElements()
{
	
	for(int n = 0, i=0; i<ActElementsCount; ++i, ++n)
	{
		Elements[i].SetStartNode(n);
	}
}